package name.sraynal.coodiary.fileprovider;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import name.sraynal.coodiary.fileprovider.handler.ConfigHandler;

import org.xml.sax.SAXException;

public class ConfigFileProvider implements IConfigProvider {

	private File configFile;
	private List<File> files;
	private Map<String, String> typeMappings;
	private Set<String> includedTypes;

	public ConfigFileProvider(File configFile) {
		super();
		this.configFile = configFile;
	}

	public Set<String> getIncludedTypes() {
		return includedTypes;
	}

	public List<File> getFiles() {
		if (this.files == null) {
			parseConfigFile();
		}
		return this.files;
	}

	private void parseConfigFile() {
		try {
			ConfigHandler ch = new ConfigHandler();
			SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
			parser.parse(this.configFile, ch);
			this.files = ch.getFiles();

			// get files under whole directories
			addWholeDirsToFiles(ch);

			this.typeMappings = ch.getTypeMappings();
			this.includedTypes = ch.getIncludedTypes();
		} catch (ParserConfigurationException e) {
			throw new RuntimeException(e);
		} catch (SAXException e) {
			throw new RuntimeException(e);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	private void addWholeDirsToFiles(ConfigHandler ch) {
		Iterator<File> dirsIt = ch.getWholeDirs().iterator();

		while (dirsIt.hasNext()) {
			File currentDir = dirsIt.next();
			Iterator<File> filesIt = Arrays.asList(currentDir.listFiles())
					.iterator();
			while (filesIt.hasNext()) {
				File currentFile = filesIt.next();
				if (currentFile.isFile()) {
					this.files.add(currentFile);
				}
			}
		}
	}

	@Override
	public Map<String, String> getTypeMappings() {
		if (this.files == null) {
			parseConfigFile();
		}
		return this.typeMappings;
	}
}
